package com.yunquan.ohana.base.ui

import android.content.Intent
import android.os.Bundle
import androidx.activity.result.ActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.databinding.DataBindingUtil
import androidx.databinding.ViewDataBinding
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProviders
import com.trello.rxlifecycle4.components.support.RxAppCompatActivity
import com.yunquan.ohana.base.ui.inter.IBaseView
import com.yunquan.ohana.dialog.LoadingDialog
import com.yunquan.ohana.ui.scan.ScanActivity
import java.lang.reflect.ParameterizedType

abstract class BaseActivity<V : ViewDataBinding, VM : BaseViewModel> :
    RxAppCompatActivity(), IBaseView {
    var binding: V? = null
    var viewModel: VM? = null
    private var viewModelId: Int? = null

    private val mActivityResult = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
        onActivityResult(result)
    }

    open fun onActivityResult(result: ActivityResult) {

    }

    override fun initParam() {}

    override fun initData(savedInstanceState: Bundle?) {}

    override fun initViewObservable() {}

    abstract fun initContentView(savedInstanceState: Bundle?): Int

    abstract fun initVariableId(): Int

    open fun initViewModel(): VM? {
        return null
    }

    fun refreshLayout() {
        if (viewModel != null) {
            binding?.setVariable(viewModelId!!, viewModel)
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        initParam()
        initViewDataBinding(savedInstanceState)
        registerUIChangeLiveDataCallBack()
        initData(savedInstanceState)
        initViewObservable()
        viewModel?.registerRxBus()
    }

    override fun onDestroy() {
        viewModel?.removeRxBus()
        binding?.unbind()
        super.onDestroy()
    }

    private fun initViewDataBinding(savedInstanceState: Bundle?) {
        binding = DataBindingUtil.setContentView(this, initContentView(savedInstanceState))
        viewModelId = initVariableId()
        viewModel = initViewModel()
        if (viewModel == null) {
            val type = javaClass.genericSuperclass
            val modelClass: Class<out ViewModel> = if (type is ParameterizedType) {
                type.actualTypeArguments[1] as Class<out ViewModel>
            } else {
                BaseViewModel::class.java
            }
            viewModel = createViewModel(this, modelClass) as VM
        }
        binding?.setVariable(viewModelId!!, viewModel)
        binding?.lifecycleOwner = this
        lifecycle.addObserver(viewModel!!)
        viewModel?.injectLifecycleProvider(this)
    }

    private fun registerUIChangeLiveDataCallBack() {

        //加载对话框显示
        viewModel?.getUIChangeLiveData()?.showDialogEvent?.observe(this) { value -> showLoading(value!!) }

        //加载对话框消失
        viewModel?.getUIChangeLiveData()?.dismissDialogEvent?.observe(this) {
            dismissLoading()
        }

        //跳入新页面
        viewModel?.getUIChangeLiveData()?.startActivityEvent?.observe(this) { params ->
            val clz = params!![ParameterField.CLASS] as Class<*>
            val bundle = params[ParameterField.BUNDLE] as Bundle?
            startActivity(clz, bundle)
        }

        //跳入新页面 带返回值
        viewModel?.getUIChangeLiveData()?.startActivityForResultEvent?.observe(this) { params ->
            val clz = params!![ParameterField.CLASS] as Class<*>
            val bundle = params[ParameterField.BUNDLE] as Bundle?
            startActivityForResult(clz, bundle)
        }

        //关闭界面
        viewModel?.getUIChangeLiveData()?.finishEvent?.observe(this) {
            finish()
        }

        //关闭上一层
        viewModel?.getUIChangeLiveData()?.onBackPressedEvent?.observe(this) {
            onBackPressedDispatcher.onBackPressed()
        }
    }

    fun showLoading(title: String? = null) {
        if (LoadingDialog.getInstance().isShowing()) {
            return
        }
        LoadingDialog.getInstance().show(title)
    }

    fun dismissLoading() {
        LoadingDialog.getInstance().dismiss()
    }

    fun startActivity(clz: Class<*>) {
        startActivity(Intent(this, clz))
    }

    fun startActivity(clz: Class<*>, bundle: Bundle?) {
        val intent = Intent(this, clz)
        bundle?.let {
            intent.putExtras(it)
        }
        startActivity(intent)
    }

    fun startActivityForResult(clz: Class<*>, bundle: Bundle?) {
        val intent = Intent(this, clz)
        bundle?.let {
            intent.putExtras(it)
        }
        mActivityResult.launch(intent)
    }

    private fun <T : ViewModel> createViewModel(activity: FragmentActivity, cls: Class<T>): T {
        return ViewModelProviders.of(activity)[cls]
    }
}